package com.helloandroid.activesitting.bl;

import java.util.ArrayList;

import com.helloandroid.activesitting.ApplicationObject;
import com.helloandroid.activesitting.bc.GPSConnector;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;

public class HomeManager extends AsyncTask<Void, Double, Void> implements
		ILocationDataReceived {

	private final GPSConnector _gpsConnector = new GPSConnector(this);
	private ArrayList<IHomeListener> _listeners = new ArrayList<IHomeListener>();
	private double _homeLatitude;
	private double _homeLongitude;
	private double _tolerance = 0;
	private boolean _atHome = false;
	private boolean _athHomeTmp = false;
	private boolean _started = false;

	public HomeManager() {
		SharedPreferences homeCoords = ApplicationObject.ApplicationContext
				.getSharedPreferences("HomeCoords", Context.MODE_PRIVATE);
		try {
			this._homeLatitude = homeCoords.getFloat("HomeLatitude", 0);
			this._homeLongitude = homeCoords.getFloat("HomeLongitude", 0);
			Log.d("HomeManager", "Loaded values: LatHome=" + String.valueOf(this._homeLatitude)
					+ " LonHome=" + String.valueOf(this._homeLongitude));
		} catch (Exception ex) {

		}
	}

	/**
	 * Call this to store last coordinates as home's location
	 */
	public void StoreHomeCoordinates(double latitude, double longitude) {
		SharedPreferences homeCoords = ApplicationObject.ApplicationContext
				.getSharedPreferences("HomeCoords", Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = homeCoords.edit();
		editor.putFloat("HomeLatitude", (float) latitude);
		editor.putFloat("HomeLongitude", (float) longitude);
		editor.commit();
		this._homeLatitude = latitude;
		this._homeLongitude = longitude;
	}
	
	/**
	 * Store current position as home location 
	 */
	public void StoreCurrentPositionAsHome() {
		this.StoreHomeCoordinates(this._homeLatitude, this._homeLongitude);
	}

	/**
	 * Register IHomeListener method for HomeListener eventhandling
	 * 
	 * @param listener
	 */
	public void RegisterHomeListener(IHomeListener listener) {
		this._listeners.add(listener);
	}

	@Override
	public void SetCoords(double latitude, double longitude) {
		this._atHome = this._arrivedHome(latitude, longitude);
//		Log.d("HomeManager", String.valueOf(this._atHome));
	}

	/**
	 * Start Async operation
	 */
	public void StartAsync() {
		this._started = true;
		this.execute();
	}

	/**
	 * Stop Async operation
	 */
	public void StopAsync() {
		this._started = false;
	}

	/**
	 * Get tolerance of GPS coordinates (percent value!!!) E.g.: 0.2 = 20%
	 * 
	 * @return double
	 */
	public double GetTolerance() {
		return _tolerance;
	}

	/**
	 * Set tolerance for GPS coordinates (percent value!!!) E.g.: 0.2 = 20%
	 * 
	 * @param _tolerance
	 *            double
	 */
	public void SetTolerance(double _tolerance) {
		this._tolerance = _tolerance;
	}

	/**
	 * Returns true if arrived to home otherwise false
	 * 
	 * @return boolean
	 */
	public boolean IsAtHome() {
		return this._atHome;
	}

	private void _runEventListeners(double latitude, double longitude, boolean athome) {
		for (IHomeListener listener : this._listeners) {
			listener.LocationChanged(latitude, longitude, athome);
		}
	}

	private boolean _arrivedHome(double lat, double lon) {
		double latVal;
		double lonVal;
		if (this._homeLatitude > lat) {
			latVal = Math.abs(this._homeLatitude % lat);
		} else {
			latVal = Math.abs(lat % this._homeLatitude);
		}
		if (this._homeLongitude > lon) {
			lonVal = Math.abs(this._homeLongitude % lon);
		} else {
			lonVal = Math.abs(lon % this._homeLongitude);
		}
//		Log.d("HomeManager", "Lat=" + String.valueOf(latVal) + " Lon%="
//				+ String.valueOf(lonVal));
		if (latVal > this._tolerance || lonVal > this._tolerance) {
			return false;
		} else {
			return true;
		}
	}

	@Override
	protected Void doInBackground(Void... params) {
		try {
			while (this._started) {
				double lat = this._gpsConnector.GetLatitude();
				double lon = this._gpsConnector.GetLongitude();
				this.SetCoords(lat, lon);
				this.publishProgress(lat, lon);
				Thread.sleep(500);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	@Override
	protected void onProgressUpdate(Double... params) {
		if (this._athHomeTmp != this._atHome) {
			this._runEventListeners(params[0], params[1], this._atHome);
			this._athHomeTmp = this._atHome;
		}
	}
}
